#ifndef _WX_PROPGRID_EDITORS_H_
#define _WX_PROPGRID_EDITORS_H_

#include "wx/textctrl.h"

class wxPGWindowList {
  public:
    wxPGWindowList() {
      m_primary = m_secondary = NULL;
    }
    void SetSecondary( wxWindow* secondary ) { m_secondary = secondary; }
    wxWindow*   m_primary;
    wxWindow*   m_secondary;
    wxPGWindowList( wxWindow* a ) {
      m_primary = a;
      m_secondary = NULL;
    };
    wxPGWindowList( wxWindow* a, wxWindow* b ) {
      m_primary = a;
      m_secondary = b;
    };
};

class WXDLLIMPEXP_PG wxPGEditor : public wxObject {
    DECLARE_ABSTRACT_CLASS( wxPGEditor )
  public:
    wxPGEditor()
      : wxObject() {
    }

    virtual ~wxPGEditor();
    virtual wxPG_CONST_WXCHAR_PTR GetName() const = 0;
    virtual wxPGWindowList CreateControls( wxPropertyGrid* propgrid, wxPGProperty* property,
                                           const wxPoint& pos, const wxSize& size ) const = 0;
#define wxPG_DECLARE_CREATECONTROLS \
  virtual wxPGWindowList CreateControls( wxPropertyGrid* propgrid, wxPGProperty* property, \
                                         const wxPoint& pos, const wxSize& sz ) const;


    virtual void UpdateControl( wxPGProperty* property, wxWindow* ctrl ) const = 0;
    virtual void DrawValue( wxDC& dc, const wxRect& rect, wxPGProperty* property, const wxString& text ) const;
    virtual bool OnEvent( wxPropertyGrid* propgrid, wxPGProperty* property, wxWindow* wnd_primary, wxEvent& event ) const = 0;
  private:
    virtual bool GetValueFromControl( wxVariant& variant, wxPGProperty* property, wxWindow* ctrl ) const WX_PG_NOT_PURE_IN_WXPYTHON;
  public:
    bool ActualGetValueFromControl( wxVariant& variant, wxPGProperty* property, wxWindow* ctrl ) const {
      return GetValueFromControl( variant, property, ctrl );
    }
    virtual void SetValueToUnspecified( wxPGProperty* property, wxWindow* ctrl ) const = 0;
    virtual void SetControlStringValue( wxPGProperty* property, wxWindow* ctrl, const wxString& txt ) const;
    virtual void SetControlIntValue( wxPGProperty* property, wxWindow* ctrl, int value ) const;
    virtual int InsertItem( wxWindow* ctrl, const wxString& label, int index ) const;
    virtual void DeleteItem( wxWindow* ctrl, int index ) const;
    virtual void OnFocus( wxPGProperty* property, wxWindow* wnd ) const;
    virtual bool CanContainCustomImage() const;
  protected:
};

#define WX_PG_DECLARE_EDITOR_CLASS(CLASSNAME) \
  DECLARE_DYNAMIC_CLASS(CLASSNAME) \
  public: \
  virtual wxPG_CONST_WXCHAR_PTR GetName() const; \
  private:

#define WX_PG_IMPLEMENT_EDITOR_CLASS(EDITOR,CLASSNAME,BASECLASS) \
  IMPLEMENT_DYNAMIC_CLASS(CLASSNAME, BASECLASS) \
  wxPG_CONST_WXCHAR_PTR CLASSNAME::GetName() const \
  { \
    return _T(#EDITOR); \
  } \
  wxPGEditor* wxPGEditor_##EDITOR = NULL; \
  wxPGEditor* wxPGConstruct##EDITOR##EditorClass() \
  { \
    wxASSERT( !wxPGEditor_##EDITOR ); \
    return new CLASSNAME(); \
  }


#define WX_PG_IMPLEMENT_EDITOR_CLASS_STD_METHODS() \
  wxPG_DECLARE_CREATECONTROLS \
  virtual void UpdateControl( wxPGProperty* property, wxWindow* ctrl ) const; \
  virtual bool OnEvent( wxPropertyGrid* propgrid, wxPGProperty* property, wxWindow* primary, wxEvent& event ) const; \
  virtual bool GetValueFromControl( wxVariant& variant, wxPGProperty* property, wxWindow* ctrl ) const; \
  virtual void SetValueToUnspecified( wxPGProperty* property, wxWindow* ctrl ) const;

class WXDLLIMPEXP_PG wxPGTextCtrlEditor : public wxPGEditor {
    WX_PG_DECLARE_EDITOR_CLASS( wxPGTextCtrlEditor )
  public:
    wxPGTextCtrlEditor() {}
    virtual ~wxPGTextCtrlEditor();
    WX_PG_IMPLEMENT_EDITOR_CLASS_STD_METHODS()
    virtual void SetControlStringValue( wxPGProperty* property, wxWindow* ctrl, const wxString& txt ) const;
    virtual void OnFocus( wxPGProperty* property, wxWindow* wnd ) const;
    static bool OnTextCtrlEvent( wxPropertyGrid* propgrid, wxPGProperty* property, wxWindow* ctrl, wxEvent& event );
    static bool GetTextCtrlValueFromControl( wxVariant& variant, wxPGProperty* property, wxWindow* ctrl );

};

class WXDLLIMPEXP_PG wxPGChoiceEditor : public wxPGEditor {
    WX_PG_DECLARE_EDITOR_CLASS( wxPGChoiceEditor )
  public:
    wxPGChoiceEditor() {}
    virtual ~wxPGChoiceEditor();
    WX_PG_IMPLEMENT_EDITOR_CLASS_STD_METHODS()
    virtual void SetControlIntValue( wxPGProperty* property, wxWindow* ctrl, int value ) const;
    virtual void SetControlStringValue( wxPGProperty* property, wxWindow* ctrl, const wxString& txt ) const;
    virtual int InsertItem( wxWindow* ctrl, const wxString& label, int index ) const;
    virtual void DeleteItem( wxWindow* ctrl, int index ) const;
    virtual bool CanContainCustomImage() const;
    wxWindow* CreateControlsBase( wxPropertyGrid* propgrid, wxPGProperty* property, const wxPoint& pos,
                                  const wxSize& sz, long extraStyle ) const;

};


class WXDLLIMPEXP_PG wxPGComboBoxEditor : public wxPGChoiceEditor {
    WX_PG_DECLARE_EDITOR_CLASS( wxPGComboBoxEditor )
  public:
    wxPGComboBoxEditor() {}
    virtual ~wxPGComboBoxEditor();
    wxPG_DECLARE_CREATECONTROLS
    virtual void UpdateControl( wxPGProperty* property, wxWindow* ctrl ) const;
    virtual bool OnEvent( wxPropertyGrid* propgrid, wxPGProperty* property,wxWindow* ctrl, wxEvent& event ) const;
    virtual bool GetValueFromControl( wxVariant& variant, wxPGProperty* property, wxWindow* ctrl ) const;
    virtual void OnFocus( wxPGProperty* property, wxWindow* wnd ) const;

};

class WXDLLIMPEXP_PG wxPGChoiceAndButtonEditor : public wxPGChoiceEditor {
    WX_PG_DECLARE_EDITOR_CLASS( wxPGChoiceAndButtonEditor )
  public:
    wxPGChoiceAndButtonEditor() {}
    virtual ~wxPGChoiceAndButtonEditor();
    wxPG_DECLARE_CREATECONTROLS
};

class WXDLLIMPEXP_PG wxPGTextCtrlAndButtonEditor : public wxPGTextCtrlEditor {
    WX_PG_DECLARE_EDITOR_CLASS( wxPGTextCtrlAndButtonEditor )
  public:
    wxPGTextCtrlAndButtonEditor() {}
    virtual ~wxPGTextCtrlAndButtonEditor();
    wxPG_DECLARE_CREATECONTROLS
};

class WXDLLIMPEXP_PG wxPGCheckBoxEditor : public wxPGEditor {
    WX_PG_DECLARE_EDITOR_CLASS( wxPGCheckBoxEditor )
  public:
    wxPGCheckBoxEditor() {}
    virtual ~wxPGCheckBoxEditor();
    WX_PG_IMPLEMENT_EDITOR_CLASS_STD_METHODS()
    virtual void DrawValue( wxDC& dc, const wxRect& rect, wxPGProperty* property, const wxString& text ) const;
    virtual void SetControlIntValue( wxPGProperty* property, wxWindow* ctrl, int value ) const;
};


#define wxPGRegisterEditorClass(EDITOR) \
  if ( wxPGEditor_##EDITOR == (wxPGEditor*) NULL ) \
  { \
    wxPGEditor_##EDITOR = wxPropertyGrid::RegisterEditorClass( wxPGConstruct##EDITOR##EditorClass(), _T(#EDITOR) ); \
  }

#define wxPGRegisterDefaultEditorClass(EDITOR) \
  if ( wxPGEditor_##EDITOR == (wxPGEditor*) NULL ) \
  { \
    wxPGEditor_##EDITOR = wxPropertyGrid::RegisterEditorClass( wxPGConstruct##EDITOR##EditorClass(), _T(#EDITOR), true ); \
  }

#define wxPG_INIT_REQUIRED_EDITOR(T) \
  wxPGRegisterEditorClass(T)


class WXDLLIMPEXP_PG wxPGEditorDialogAdapter : public wxObject {
    DECLARE_ABSTRACT_CLASS( wxPGEditorDialogAdapter )
  public:
    wxPGEditorDialogAdapter()
      : wxObject() {
    }
    virtual ~wxPGEditorDialogAdapter() { }
    bool ShowDialog( wxPropertyGrid* propGrid, wxPGProperty* property );
    virtual bool DoShowDialog( wxPropertyGrid* propGrid, wxPGProperty* property ) = 0;
    void SetValue( wxVariant value ) {
      m_value = value;
    }
    wxVariant& GetValue() {
      return m_value;
    }
  protected:
  private:
    wxVariant m_value;
};

class WXDLLIMPEXP_PG wxPGMultiButton : public wxWindow {
  public:
    wxPGMultiButton( wxPropertyGrid* pg, const wxSize& sz );
    virtual ~wxPGMultiButton() { }
    wxWindow* GetButton( unsigned int i ) { return ( wxWindow* ) m_buttons[i]; }
    const wxWindow* GetButton( unsigned int i ) const { return ( const wxWindow* ) m_buttons[i]; }
    int GetButtonId( unsigned int i ) const { return GetButton( i )->GetId(); }
    int GetCount() const { return ( int ) m_buttons.size(); }
    void Add( const wxString& label, int id = -2 );
   void Add( const wxBitmap& bitmap, int id = -2 );
    wxSize GetPrimarySize() const {
      return wxSize( m_fullEditorSize.x - m_buttonsWidth, m_fullEditorSize.y );
    }
    void FinalizePosition( const wxPoint& pos ) {
      Move( pos.x + m_fullEditorSize.x - m_buttonsWidth, pos.y );
    }
  protected:
    int GenId( int id ) const;
    wxArrayPtrVoid  m_buttons;
    wxSize          m_fullEditorSize;
    int             m_buttonsWidth;
};

WXDLLIMPEXP_PG bool wxPG_TextCtrl_SetMargins( wxWindow* tc,const wxPoint& margins );


#endif
